﻿namespace HostsIt
{
	using System;
	using System.IO;
	using System.Windows.Forms;

	using HostsIt.Properties;

	internal static class Presenter
	{
		internal static string DefaultUserStatePath
		{
			get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "HostsIt"); }
		}

		internal static string SystemHostsFileName
		{
			get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), @"drivers\etc\hosts"); }
		}

		public static string PathToJSON
		{
			get { return Settings.Default.PathToJSON != null ? Settings.Default.PathToJSON.LocalPath : string.Empty; }
			set { Settings.Default.PathToJSON = new Uri(value, UriKind.Absolute); }
		}

		public static string BackupHostsFile
		{
			get { return Settings.Default.BackupHostsFile != null ? Settings.Default.BackupHostsFile.LocalPath : string.Empty; }
			set { Settings.Default.BackupHostsFile = new Uri(value, UriKind.Absolute); }
		}

		internal static String OpenFile(String filter, String title, String initialDirectory, String initialFileName)
		{
			using (OpenFileDialog ofd = new OpenFileDialog())
			{
				ofd.ShowHelp = false;
				ofd.ShowReadOnly = false;
				ofd.CheckFileExists = true;
				ofd.CheckPathExists = true;
				ofd.Filter = filter;
				ofd.Title = title;
				ofd.InitialDirectory = initialDirectory;
				ofd.FileName = initialFileName;
				ofd.RestoreDirectory = true;

				DialogResult dr = ofd.ShowDialog();
				return dr == DialogResult.OK ? ofd.FileName : string.Empty;
			}
		}

		internal static String SaveFile(String filter, String title, String initialDirectory, String initialFileName)
		{
			using (SaveFileDialog sfd = new SaveFileDialog())
			{
				sfd.ShowHelp = false;
				sfd.CheckFileExists = false;
				sfd.CheckPathExists = true;
				sfd.Filter = filter;
				sfd.Title = title;
				sfd.InitialDirectory = initialDirectory;
				sfd.FileName = initialFileName;
				sfd.RestoreDirectory = true;

				DialogResult dr = sfd.ShowDialog();
				return dr == DialogResult.OK ? sfd.FileName : string.Empty;
			}
		}

		internal static void CreateStateDirectoryIfNecessary()
		{
			string dir = Path.GetDirectoryName(BackupHostsFile);
			try
			{
				if (!Directory.Exists(dir))
				{
					Directory.CreateDirectory(dir);
				}
			}
			catch (IOException)
			{
			}
		}

		/// <summary>
		/// Securely moves a file to a new location. Overwrites any
		/// preexisting file at new location (= replacing file).
		/// </summary>
		/// <remarks>
		/// If NTFS is available this is done via File.Replace.
		/// If NTFS is not available it will be moved via deleting
		/// any preexisting file and moving. Do NOT rely on the
		/// backupFile being there - or not - after the move process.
		/// That is not predetermined. This method is clearly
		/// optimized for the case that NTFS is available. Consider NOT
		/// using it on any other filesystem, if performance is an issue!
		/// </remarks>
		/// <param name="sourceLocation">The file to be  moved.</param>
		/// <param name="targetLocation">The new resting place of the file.</param>
		/// <param name="backupLocation">A backup location that is used when replacing on NTFS.</param>
		internal static void FileMove(String sourceLocation, String targetLocation, String backupLocation)
		{
			if (File.Exists(targetLocation))
			{
				try
				{
					File.Replace(sourceLocation, targetLocation, backupLocation, true);
				}
				catch (PlatformNotSupportedException)
				{
					// Not operating on an NTFS volume
					if (Directory.Exists(targetLocation))
					{
						File.Delete(targetLocation);
					}
					File.Move(sourceLocation, targetLocation);
				}
			}
			else
			{
				File.Move(sourceLocation, targetLocation);
			}
		}

		internal static void Disable()
		{
			string tmp = BackupHostsFile + ".tmp";
			FileMove(BackupHostsFile, SystemHostsFileName, tmp);
			FileMove(tmp, BackupHostsFile, Path.GetTempFileName());
		}

		internal static void Enable()
		{
			throw new NotImplementedException();
		}
	}
}